#Cria um objeto simulador
set ns [new Simulator]
#Cria um ponteiro para o arquivo out.nam
set nf [open out.nam w]

#Cria um ponteiro para o arquivo do Xgraph
set tr [open out.tr w]

#Indica para o simulador que os dados da simulação devem ser escritos no arquivo
#apontado por nf
$ns namtrace-all $nf

########### Procedimento responsável por finalizar o arquivo de trace e iniciar o nam #######################
proc finish {} {
    #Variáveis ns e nf são globais e podem ser modificadas dentro do método
    global ns nf tr 
    #Realiza o flush dos buffers de escrita no arquivo
    $ns flush-trace
    #Fecha os arquivos
    close $nf
    close $tr
    #Executa o nam em background, passando como argumento o arquivo gerado pela
    #simulação
    #exec nam out.nam &
    #exec xgraph out.tr -geometry 800x600 &
    exit 0
}

########################### procedimento para calculo de dados ##############
#!!! Escolha somente um dos dois para executar na simulacao !!!
proc calcPeriodicoBW {} {
    global recebe tr tcp 
    #Copia da variavel do simulador
    set ns [Simulator instance]
    #Intervalo de tempo em que sera feito o calculo
    set time 0.5 

    #Calculo dos bytes recebidos pelo no final
    set bytesRecebidos [$recebe set bytes_]

    #Pega tempo atual
    set now [$ns now]

    #Calculo da bandwidth (em Mbits/s) e escreve no arquivo do Xgraph
    puts $tr "$now [expr $bytesRecebidos*8/($time*1000000)]"
    
    #Reseta contagem dos bytes recebidos no NO final
    $recebe set bytes_ 0

    #Re-escalona prodecimento
    $ns at [expr $now+$time] "calcPeriodicoBW"
}
############# Topologia ###############

#Cria os 3 nós
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]

#Enlaces que conectam os nós
$ns duplex-link $n0 $n1 10Mb 2ms DropTail 
$ns duplex-link $n1 $n2 1Mb  1ms DropTail 

#Monitorar filas
$ns duplex-link-op $n0 $n1 queuePos 0.5
$ns duplex-link-op $n1 $n2 queuePos 0.5

#Definir tamanho do buffer/fila ?
$ns queue-limit $n1 $n2 10

#Os diferentes tipos de TCP sao
# Agent/TCP -> Tahoe
# Agent/TCP/Reno 
# Agent/TCP/Newreno
# Agent/TCP/Sack1 -> Selective Repeat
# Agent/TCP/Vegas
# Agent/TCP/Fack -> Reno com .forward ack
#Agente TCP de envio
set tcp [new Agent/TCP/Sack1]

#Seta o no0 como o de envio
$ns attach-agent $n0 $tcp

#Os diferentes tipos de recepcao de TCP sao
#Agent/TCPSink -> Um ACK por pacote
#Agent/TCPSink/DelACK -> Delay do envio do ACK configuravel
#Agent/TCPSink/Sack1 -> ACK seletivo
#Agent/TCPSink/Sack1/DelACK -> ACK seletivo com delay configuravel
#Agente TCP de recepcao
set recebe [new Agent/TCPSink]

#Seta o no2 como o de recepcao
$ns attach-agent $n2 $recebe

#Conecta o no de envio ao de recepcao
$ns connect $tcp $recebe

#Cria uma aplicacao que gera o trafego
set ftp [new Application/FTP]

$ftp attach-agent $tcp

#############################

#Seta cor dos pacotes
$tcp set class_ 1
$ns color 1 Blue


##############################

#Eventos da simulacao
#$ns at 0.0 "calcPeriodicoBW"
$ns at 0.0 "$ftp start"
$ns at 0.0 "calcPeriodicoBW"
$ns at 15.0 "$ftp stop"
$ns at 15.5 "finish"

$ns run
